package org.zeroes.common_prelude;

public class CollisionPoly {
	
	public double[] pts_cache;
	public double[] pts_array;
	public int cache_width ;
	public int cache_height ;
	public double cache_angle ;
	public int pts_count ;
	public Util cr = new Util();
	public  CollisionPoly(double[] pts_array_){

		set_pts(pts_array_);
		
	}
	
	protected void set_pts(double[] pts_array_){
		this.pts_array = pts_array_;
		this.pts_count = pts_array_.length / 2;			// x, y, x, y... in array
		//this.pts_cache.length = pts_array_.length;
		
		// invalidate cache
		this.cache_width = -1;
		this.cache_height = -1;
		this.cache_angle = 0;
		
	}
	
	public boolean is_empty(){
		
		return pts_array.length>0 ? false : true;
	}
	
	public void set_from_quad(Quad q, double offx, double offy, int w, int h){
		
		this.pts_count = 4;
		this.pts_cache[0] = q.tlx - offx;
		this.pts_cache[1] = q.tly - offy;
		this.pts_cache[2] = q.trx - offx;
		this.pts_cache[3] = q.try_ - offy;
		this.pts_cache[4] = q.brx - offx;
		this.pts_cache[5] = q.bry - offy;
		this.pts_cache[6] = q.blx - offx;
		this.pts_cache[7] = q.bly - offy;
		this.cache_width = w;
		this.cache_height = h;
		
	}
	
	public void cache_poly(int w, int h, double a){
		if (this.cache_width == w && this.cache_height == h && this.cache_angle == a)
			return;		// cache up-to-date
			
		// Set the points cache to the scaled and rotated poly
		this.cache_width = w;
		this.cache_height = h;
		this.cache_angle = a;
		
		int i, len;
		double x, y;
		double sina = 0;
		double cosa = 1;
		
		if (a != 0)
		{
			sina = Math.sin(a);
			cosa = Math.cos(a);
		}
		
		for (i = 0, len = this.pts_count; i < len; i++)
		{
			// get scaled
			x = this.pts_array[i*2] * w;
			y = this.pts_array[i*2+1] * h;
			
			// rotate by angle and save in cache
			this.pts_cache[i*2] = (x * cosa) - (y * sina);
			this.pts_cache[i*2+1] = (y * cosa) + (x * sina);
		}
		
	}
	
	public boolean contains_pt(double a2x,double a2y){
		
		if (a2x == this.pts_cache[0] && a2y == this.pts_cache[1])
			return true;
		
		// Determine start coordinate outside of poly
		// Test 2 different start coordinates to ensure segments passing exactly
		// through vertices don't give false negatives
		int a1x = -this.cache_width * 5 - 1;
		int a1y = -this.cache_height * 5 - 1;
		int a3x = this.cache_width * 5 + 1;
		int a3y = -1;
		double b1x, b1y, b2x, b2y;
		int i, len;
		
		// count segments intersecting from given start points
		int count1 = 0, count2 = 0;
		
		for (i = 0, len = this.pts_count; i < len; i++)
		{
			b1x = this.pts_cache[i*2];
			b1y = this.pts_cache[i*2+1];
			b2x = this.pts_cache[((i+1)%len)*2];
			b2y = this.pts_cache[((i+1)%len)*2+1];
			
			if (cr.segments_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y))
				count1++;
			if (cr.segments_intersect(a3x, a3y, a2x, a2y, b1x, b1y, b2x, b2y))
				count2++;
		}
		
		// In theory both counts should always be even or odd at the same time.
		// However, if one of the segments passes exactly through a vertex then the count will incorrectly be even.
		// In that case the other line should still have an odd count.  Therefore, return
		// true if either count was odd.
		return (count1 % 2 == 1) || (count2 % 2 == 1);
		
	}
	
	public boolean intersects_poly(CollisionPoly rhs,double offx, double offy){
		
		if (this.contains_pt(rhs.pts_cache[0] + offx, rhs.pts_cache[1] + offy))
			return true;
		// Determine if rhs contains this
		if (rhs.contains_pt(this.pts_cache[0] - offx, this.pts_cache[1] - offy))
			return true;
			
		// Check all combinations of segment intersection
		// TODO: could be faster with a sweep
		int i, leni, j, lenj;
		double a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y;
		
		for (i = 0, leni = this.pts_count; i < leni; i++)
		{
			a1x = this.pts_cache[i*2];
			a1y = this.pts_cache[i*2+1];
			a2x = this.pts_cache[((i+1)%leni)*2];
			a2y = this.pts_cache[((i+1)%leni)*2+1];
			
			for (j = 0, lenj = rhs.pts_count; j < lenj; j++)
			{
				b1x = rhs.pts_cache[j*2] + offx;
				b1y = rhs.pts_cache[j*2+1] + offy;
				b2x = rhs.pts_cache[((j+1)%lenj)*2] + offx;
				b2y = rhs.pts_cache[((j+1)%lenj)*2+1] + offy;
				
				if (cr.segments_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y))
					return true;
			}
		}
		
		return false;
	
	}
	
}
